package de.gameduell.framework.application.net {

	import de.gameduell.framework.debug.Debug;
	import flash.events.DataEvent;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.HTTPStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.net.URLVariables;	

	/**
	 * An easy to use URL-request.
	 * It basically wrappes the original Flash URLRequest and handles
	 * all incomming events and errors.
	 */
	public class SimpleURLRequest extends EventDispatcher {
		
		public static const ERROR:String = "simpleRequestError";
		
		private var loader:URLLoader;
		private var myRequest:URLRequest;
		private var variables:URLVariables;
		private var errorSent:Boolean;

		/**
		 * Class constructor
		 * 
		 * @param anURL			target url
		 * @param aVariables	[optional] bunch of url variables
		 * @param sendMethod	[optional] requests send method GET or POST - default is POST
		 */
		public function SimpleURLRequest(anURL:String, aVariables:URLVariables = null, sendMethod:String = "POST"){
			loader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, completeHandler);
			loader.addEventListener(ProgressEvent.PROGRESS, progressHandler);
			loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
            loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
            loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
            
			myRequest = new URLRequest(anURL);
            myRequest.method = sendMethod == "POST" ? URLRequestMethod.POST : URLRequestMethod.GET;
            
			variables = aVariables == null ? new URLVariables() : aVariables;
			errorSent = false;
		}

		/**
		 * Submit the URLRequest to a given URL.
		 */
		public function load():void {
			try {
				if(variables.toString().length > 0){
					myRequest.data = variables;
				}
				loader.load(myRequest);
			}
			catch(error:Error) {
				Debug.trace("SimpleURLRequest::Unable to load requested document. " + error.getStackTrace(), Debug.WARNING);
			}        	
        }

		/**
		 * Add an URL variable to this URLRequest.
		 * @param varName		name of the url variable
		 * @param varValue		value of the url variable
		 */
		public function addVariable(varName:String, varValue:String):void {
			variables[varName] = varValue;
		}
		
		/**
		 * Set a whole bunch of url variables.
		 * @param aVariables	set of url variables
		 */
		public function addVariables(aVariables:URLVariables):void {
			variables = aVariables;
		}
		
		/**
		 * General error handler. Dispatches the first error which occurred. 
		 */
		private function onRequestError(errorType:String):void {
			Debug.trace("SimpleURLRequest::onRequestError: " + errorType, Debug.WARNING);
			if(!errorSent){
				errorSent = true;
				dispatchEvent(new Event(ERROR));
			}
		}
		
		/**
		 * Re-dispatch of the onProgress-event.
		 */
		private function progressHandler(event:ProgressEvent):void {
			dispatchEvent(event);
		}
		
		/**
		 * Will be called after a request succeeded.
		 */
        private function completeHandler(event:Event):void {
            var loader:URLLoader = URLLoader(event.target);
            dispatchEvent(new DataEvent(DataEvent.DATA, false, false, loader.data));
        }

		/**
		 * Handler for security events.
		 * Re-Dispatch via a general error handler.
		 * @param event		SecurityErrorEvent.SECURITY_ERROR 
		 */
		private function securityErrorHandler(event:SecurityErrorEvent):void {
            onRequestError(String(event));
		}

		/**
		 * Handler for http status messages.
		 * Re-Dispatch via a general error handler.
		 * @param event		SecurityErrorEvent.SECURITY_ERROR 
		 */
        private function httpStatusHandler(event:HTTPStatusEvent):void {
            if(event.status >= 400){
            	onRequestError(String(event));
            }
		}

		/**
		 * Handler for IO errors.
		 * Re-Dispatch via a general error handler.
		 * @param event		IOErrorEvent.IO_ERROR
		 */
        private function ioErrorHandler(event:IOErrorEvent):void {
            onRequestError(String(event));
		}
	}
}
